package cn.lghuntfor.commons.common.async;


import cn.lghuntfor.commons.common.constants.TTL;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 异步/线程池工具类
 * @author liaogang
 * @date 2021/2/5 11:03
 */
public class AsyncUtils {

    /** 通用线程池 */
    private static ThreadPoolExecutor COMMON_POOL = null;

    /** 线程工厂匿名 */
    private static final ThreadFactory THREAD_FACTORY = new ThreadFactory() {
        private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
        private final AtomicInteger threadNumber = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = this.defaultFactory.newThread(r);
            if (!thread.isDaemon()) {
                thread.setDaemon(true);
            }
            thread.setName("ndccloud-async-" + this.threadNumber.getAndIncrement());
            return thread;
        }
    };

    /**
     * 获取通用线程池
     * @author liaogang
     * @date 2021/2/5 11:10
     * @return java.util.concurrent.ThreadPoolExecutor
     */
    public static ThreadPoolExecutor getPool() {
        if (COMMON_POOL != null) {
            return COMMON_POOL;
        }
        synchronized (AsyncUtils.class) {
            if (COMMON_POOL == null) {
                int processors = Runtime.getRuntime().availableProcessors();
                COMMON_POOL = new ThreadPoolExecutor(processors * 2, processors * 10
                    , TTL.M1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5000)
                    , THREAD_FACTORY);
            }
        }
        return COMMON_POOL;
    }

    /**
     * 执行任务
     * @author liaogang
     * @date 2021/2/5 11:11
     * @param runnable
     * @return void
     */
    public static void run(Runnable runnable) {
        getPool().execute(runnable);
    }

    /**
     * 执行有返回值的任务
     * @author liaogang
     * @date 2021/2/5 11:11
     * @param callable
     * @return java.util.concurrent.Future<V>
     */
    public static <V> Future<V> call(Callable<V> callable) {
        return getPool().submit(callable);
    }

}
